package proxy

import (
	"github.com/prometheus/client_golang/prometheus"
	"go-proxy/config"
	"net/http"
	"strconv"
	"sync/atomic"
)

var (
	ServerRequestNum int64 = 0
	// 代理服务器请求统计
	serverRequestTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "server_requests_total",
			Help: "代理服务器请求统计",
		},
		[]string{"name", "port", "type"},
	)

	// 代理服务器请求状态码统计
	serverRequestCodeTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "server_requests_code_total",
			Help: "代理服务器请求状态码统计",
		},
		[]string{"name", "port", "type", "code"},
	)

	ActiveConnectionsNum int64 = 0
	// 活跃总连接数统计
	activeConnectionsTotal = prometheus.NewGauge(prometheus.GaugeOpts{
		Name: "active_connections_total",
		Help: "活跃总连接数统计",
	})

	// 代理服务活跃总连接数统计
	serverActiveConnections = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "server_active_connections",
			Help: "代理服务活跃总连接数统计",
		},
		[]string{"name", "port", "type"},
	)

	// 代理接口请求数量统计
	apiRequestTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "api_requests_total",
			Help: "代理接口请求数量统计",
		},
		[]string{"name", "port", "type", "url"},
	)

	uploadBytesTotal = prometheus.NewCounter(prometheus.CounterOpts{
		Name: "upload_bytes_total",
		Help: "Total number of bytes uploaded.",
	})

	downloadBytesTotal = prometheus.NewCounter(prometheus.CounterOpts{
		Name: "download_bytes_total",
		Help: "Total number of bytes downloaded.",
	})

	slowRequestCostTime = prometheus.NewSummaryVec(
		prometheus.SummaryOpts{
			Name: "slow_request_cost_time",
			Help: "慢请求接口统计",
		},
		[]string{"name", "port", "type", "url"},
	)
)

func MetricsInit() {
	// 注册自定义指标
	prometheus.MustRegister(serverRequestTotal)
	prometheus.MustRegister(serverRequestCodeTotal)
	prometheus.MustRegister(activeConnectionsTotal)
	prometheus.MustRegister(serverActiveConnections)
	prometheus.MustRegister(apiRequestTotal)
	prometheus.MustRegister(uploadBytesTotal)
	prometheus.MustRegister(downloadBytesTotal)
	prometheus.MustRegister(slowRequestCostTime)
}

func IncServerRequestTotal(server *config.ProxyServer) {
	serverRequestTotal.WithLabelValues(server.Name, strconv.Itoa(server.Port), server.Type).Inc()
	atomic.AddInt64(&ServerRequestNum, 1)
}

func IncServerRequestCodeTotal(server *config.ProxyServer, code int) {
	serverRequestCodeTotal.WithLabelValues(server.Name, strconv.Itoa(server.Port), server.Type, strconv.Itoa(code)).Inc()
}

func IncActiveConnectionsTotal() {
	activeConnectionsTotal.Inc()
	atomic.AddInt64(&ActiveConnectionsNum, 1)
}

func DecActiveConnectionsTotal() {
	activeConnectionsTotal.Dec()
	atomic.AddInt64(&ActiveConnectionsNum, -1)
}

func IncServerActiveConnections(server *config.ProxyServer) {
	serverActiveConnections.WithLabelValues(server.Name, strconv.Itoa(server.Port), server.Type).Inc()
}

func DecServerActiveConnections(server *config.ProxyServer) {
	serverActiveConnections.WithLabelValues(server.Name, strconv.Itoa(server.Port), server.Type).Dec()
}

func IncApiRequestTotal(server *config.ProxyServer, r *http.Request) {
	apiRequestTotal.WithLabelValues(server.Name, strconv.Itoa(server.Port), server.Type, r.URL.Path).Inc()
}

func HandleServerBeforeMetrics(server *config.ProxyServer) {
	IncServerRequestTotal(server)
	IncActiveConnectionsTotal()
	IncServerActiveConnections(server)
}

func HandleServerAfterMetrics(server *config.ProxyServer) {
	DecActiveConnectionsTotal()
	DecServerActiveConnections(server)
}

func AddUploadBytes(bytes int64) {
	if bytes < 0 {
		return
	}
	uploadBytesTotal.Add(float64(bytes))
}

func AddDownloadBytes(bytes int64) {
	if bytes < 0 {
		return
	}
	downloadBytesTotal.Add(float64(bytes))
}

func AddSlowRequestCostTime(server *config.ProxyServer, r *http.Request, cost int64) {
	if cost > 3000 {
		slowRequestCostTime.WithLabelValues(server.Name, strconv.Itoa(server.Port), server.Type, r.URL.Path).Observe(float64(cost))
	}
}
